#ifndef WIDGET_H
#define WIDGET_H

#include "ui_Widget.h"
#include "MySqlQueryModel.h"
#include "ConfigurarMesas.h"
#include "LogInDialog.h"
#include "FreeTableDlg.h"
#include "PrinterPdf.h"
#include "FtpClient.h"
#include "Parametros.h"
#include "smtp.h"

#include <QDesktopWidget>
#include <QMessageBox>
#include <QSqlRecord>
#include <QSqlQuery>
#include <QSqlError>
#include <QKeyEvent>
#include <QProcess>
#include <QDebug>
#include <QTimer>
#include <QTime>
#include <QMap>
#include <QPlainTextEdit>

#include <cups/cups.h>


class Widget : public QWidget, private Ui::Widget
{
    Q_OBJECT
    
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
private:
    int nTables;    // number of tables
    ConfigurarMesas TableConf;

    enum    table_t{ undefined = 0, billar, billas, pool }          isSelectType;   // table types
    enum    table_s{ Unknown = -1, Disabled, Enabled, Reserved }    status;         // possible status of a table
    QSqlDatabase    db;

    QProcess        *soundProcess;
    MySqlQueryModel *Modelo[23];    // 16 + 4 + 3 tables, static value
    PrinterPdf      *printer;
    FtpClient       *ftp;
    Smtp            *smtp;
    QTimer          *timer;
    Parametros      param;

    int     visibleRows;
    int     tableId;
    int     counter;                // timer's counter
    int     upperLimit;
    bool    bCheck;
    bool    bIsEnabledTableSelected;    // Enabled Table is selected
    QString report;
    QString dateTimeReport;

    /// list of all table by type <table_id, description>
    QMap<int, QString>  allBillarTables;
    QMap<int, QString>  allBillasTables;
    QMap<int, QString>  allPoolTables;

    /// <table_id, table_s>
    QMap<int, table_s>  statusTable;    // tables and its state
//    QMap<QString, QDateTime>    freeTable;

    QStringList intervals;
    QStringList enbTables;              // enabled table's list
    QStringList disTables;              // disabled table's list
    QStringList freTables;

    QPlainTextEdit *msg;

    /*
      table_rentals;
    +-----------------+----------+---------------------+---------+-------+
    | table_rental_id | table_id | init_time           | minutes | money |
    +-----------------+----------+---------------------+---------+-------+
      tables;
    +----------+-------------+------+
    | table_id | description | type |
    +----------+-------------+------+
    */
    QString fld_tri;
    QString fld_tid;
    QString fld_i_t;
    QString fld_min;
    QString fld_mon;
    QString fld_dsc;
    QString fld_typ;

    void initialize();
    bool connection(int host = 0);
    void setModels();
    void startTimer();
    ///
    void playSound();
    ///
    void homework();
    ///
    bool printPdfFile();
    ///
    bool uploadPdfFile();
    /// Compara si la lista de mesas rentadas ha cambiado cada minuto
    /// actualiza las listas del tab actual con updateTableList
    void            checkEnabledTableList();

    ///
    /// \brief getIdOfTable encuentra el id correspondiente a la descripción de la mesa
    /// \param description
    /// \return Id de la mesa, 0 significa que no encontró la mesa con la descripción dada
    ///
    int     getIdOfTable(QString description);

    table_t getTypeOfTable(int tableId);

    // calcula si la mesa está habilitada para ser rentada, se calcula utilizando el tiempo actual
    // por ello, las mesas deben figurar en la tabla table_rentals, por ejemplo para la Mesa 17
    // > insert into table_rentals (table_id, minutes, money) values(17, 0, 0);
    ///
    /// \brief queryTablesStatus
    ///
    ///
    /*
    +----------+--------+
    | table_id | diff   |
    +----------+--------+
    |       23 |  31854 |
    |       22 |  31854 |
    |       ...|     ...|
    |        1 |   2840 |
    +----------+--------+
    */
    ///
    /// \return
    ///
    QMap<int, table_s> queryTablesStatus();
    /// Rentals shown in tableViews
    QString         queryRentalsByTable(int tableId);
    ///
    /// \brief queryFillTableLists make a query to get the complete list of tables (all of types)
    ///
    void            queryFillTableLists();
    /// get the statusTables private member, keep the current satus of tables & it's required first
    void            getStatusTables();
    /// get list of tables by type and status
    QStringList     getListOfTablesByTypeByStatus(int iTableType, table_s status = Enabled);
    /// calculate Price
    float           calculateRental(table_t type, const int minutes);
    /// insert into database
    bool            queryInsertIntoRentalsTable(int tableId, int interval, float rental);
    ///
    /// \brief  Obtiene el conjutno de mesas libres que han sido rentadas con la opción [libre]
    /// \return Lista de las mesas que fueron insertadas con un tiempo de 1440 minutos
    ///
    bool            querySelectFreeTables(QMap<QString, QDateTime> &freeTable);

    ///
    /// \brief queryUpdateRowFromRentalsTable actualiza en la tabla table_rentals la renta
    ///        calculada para una mesa que adicionó tiempo extra
    /// \param rentalId
    /// \param interval
    /// \param rental
    /// \return
    ///
    bool            queryUpdateRowFromRentalsTable(const int rentalId, const int interval, const float rental);

    ///
    /// \brief queryUpdateRowFromRentalsTable actualiza en la tabla table_rentals la renta
    ///        calculada de una mesa libre
    /// \param rentalId
    /// \param interval
    /// \param rental
    /// \return
    ///
    bool            queryUpdateRowFromRentalsTable(const QString freeTable, const int interval, const float rental);
    ///
    bool            querySelectLastRowByTableId(const int tableId, int &rentalId, QDateTime &initTime, int &interval);
    /// update tables list by type
    void            updateTablesListsByType(table_t type);
    /// update time's intervals at cbDifTiempo
    void            updateIntervalCbx();
    ///
    bool            queryWriteReportToFile();
    ///
    bool            verifyUser(QString user, QString pass);


private slots:
    /// show digital watch
    void            showDigitalWatch();
    void timerHit();
    void btSalirSlot();
    void btAsignarSlot();
    void btAdicionarSlot();
    void soundPlayEnd(int code);
    void finishedPrint();
    void finishFileUpload(bool error);
    void mailSent(QString status);
    ///
    /// \brief updateFreeTableSlot
    /// \param freeTable : descripción de la mesa
    /// \param elapsedTime : minutos de renta transcurridos para la mesa
    ///
    void updateFreeTableSlot(QString freeTable, int elapsedTime);

    ///
    /// \brief on_tabWidget_currentChanged
    /// \param index que representa el tipo de mesa seleccionada en función de la pestaña activa
    ///
    void on_tabWidget_currentChanged(int index = 0);
    /// these two tables are interconnected
    void on_lstDisTables_itemClicked(QListWidgetItem *item);
    void on_lstEnbTables_itemClicked(QListWidgetItem *item);
    /// this slot lauch log in dialog
    void openDialog();

protected:
    // only one key
    virtual void keyPressEvent(QKeyEvent *event);

signals:
    void    printFile();
    void    uploadFile();
};

#endif // WIDGET_H
